package com.itheima.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.constant.MessageConstant;
import com.itheima.dao.MenuDao;
import com.itheima.dao.UserDao;
import com.itheima.entity.PageResult;
import com.itheima.pojo.Menu;
import com.itheima.pojo.User;
import com.itheima.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wuzhouwei
 * @date 2020/4/16
 */
@Service(interfaceClass = MenuService.class)
@Transactional
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuDao menuDao;

    @Autowired
    private JedisPool jedisPool;

    @Autowired
    private UserDao userDao;

    /**
     * 根据当前登录的用户查询当前用户菜单权限
     *
     * @param username
     * @return
     */
    @Override
    public List<Menu> queryMenu(String username) {
        // 先从redis中查是否有缓存这个用户的菜单权限
        // TODO--当修改用户的菜单权限时.需要更新redis
        Jedis jedis = jedisPool.getResource();
        String menuListStr = jedis.get("MENU_LIST_" + username);
        if (menuListStr != null && menuListStr.length() > 0) {
            List<Menu> menuList = (List<Menu>) JSON.parse(menuListStr);
            return menuList;
        }
        List<Menu> menuList = menuDao.queryParentMenu(username);
        // 根据父菜单和username再查询其子菜单
        Map<String, Object> map = new HashMap<>();
        if (menuList != null && menuList.size() > 0) {
            for (Menu menu : menuList) {
                map.put("parentId",menu.getId());
                map.put("username",username);
                List<Menu> childrenList = menuDao.queryChildrenMenu(map);
                menu.setChildren(childrenList);
            }
        }
        // 存入redis中
        jedis.set("MENU_LIST_" + username, JSON.toJSONString(menuList));
        return menuList;
    }


    @Override
    public PageResult findPage(Integer currentPage, Integer pageSize, String queryString) {

        List<Menu> menuList = null;
        if (StringUtils.isEmpty(queryString)) {
            PageHelper.startPage(currentPage, pageSize);
            menuList = menuDao.findAll();
        } else {
            PageHelper.startPage(currentPage, pageSize);
            menuList = menuDao.findByCondition(queryString);
        }


        PageInfo<Menu> pageInfo = new PageInfo<Menu>(menuList);
        List<Menu> list = pageInfo.getList();
        List<Menu> resultList = new ArrayList<>();
        for (Menu menu : list) {
            String parentName = menuDao.findParentNameByParentMenuId(menu.getParentMenuId());
            menu.setParentName(parentName);
            resultList.add(menu);
        }
        return new PageResult(pageInfo.getTotal(), resultList);
    }

    @Override
    public Menu findByMenuId(Integer id) {
        return menuDao.findByMenuId(id);
    }

    @Override
    public void editMenu(Menu menu) {
        if (menu != null) {
            int count1 = menuDao.findMenuCountByNameAndId(menu);
            if (count1 > 0) {
                throw new RuntimeException(MessageConstant.SET_MENU_NAME_FAIL);
            }

            int count2 = menuDao.findMenuCountByLinkUrlAndId(menu);
            if (count2 > 0) {
                throw new RuntimeException(MessageConstant.SET_MENU_LINK_URL_FAIL);
            }

            int count3 = menuDao.findMenuCountByPathAndId(menu);
            if (count3 > 0) {
                throw new RuntimeException(MessageConstant.SET_MENU_PATH_FAIL);
            }

            menuDao.editMenu(menu);

            // 根据当前菜单查询出来。有该菜单关联的角色列表。再关联查出角色关联的用户列表。
            // 再redis中获取这些用户的MENU_LIST_#{username}，对应的值。
            // 如果值为空。则查询该用户的List<Menu>并转换成json字符串以MENU_LIST_#{username}为键，json串为值存入redis中。这样该用户重新登录就能看到变更的菜单。
            // 如果值为空。则不用管。
            List<String> usernames = userDao.findUserListByMenuId(menu.getId());
            Jedis jedis = jedisPool.getResource();
            if (usernames != null && usernames.size() > 0) {
                for (String username : usernames) {
                    // 从redis拿当前用户名对应的key的值.
                    String menuListStr = jedis.get("MENU_LIST_" + username);
                    // 如果不为空则更新一下redis
                    if (menuListStr != null) {
                        List<Menu> menuList = menuDao.queryParentMenu(username);
                        // 根据父菜单和username再查询其子菜单
                        Map<String, Object> map = new HashMap<>();
                        if (menuList != null && menuList.size() > 0) {
                            for (Menu p_menu : menuList) {
                                map.put("parentId", p_menu.getId());
                                map.put("username", username);
                                List<Menu> childrenList = menuDao.queryChildrenMenu(map);
                                p_menu.setChildren(childrenList);
                            }
                        }
                        // 存入redis中
                        jedis.set("MENU_LIST_" + username, JSON.toJSONString(menuList));
                    }
                }
            }
        }

    }

    @Override
    public void delete(Integer id) {
        int count = menuDao.findRoleCountById(id);
        if (count > 0) {
            throw new RuntimeException(MessageConstant.DELETE_MENU_ASSOCIATE_ROLE_FAIL);
        }

        int count2 = menuDao.findSubMenuCountById(id);
        if(count2 > 0){
            throw new RuntimeException("该菜单有子菜单, 不能删除");
        }

        menuDao.delete(id);
    }

    @Override
    public void addMenu(Menu menu) {
        if (menu != null) {
            int count1 = menuDao.findMenuCountByName(menu.getName());
            if (count1 > 0) {
                throw new RuntimeException(MessageConstant.ADD_MENU_NAME_FAIL);
            }

            int count2 = menuDao.findMenuCountByLinkUrl(menu.getLinkUrl());
            if (count2 > 0) {
                throw new RuntimeException(MessageConstant.ADD_MENU_LINK_URL_FAIL);
            }

            int count3 = menuDao.findMenuCountByPath(menu.getPath());
            if (count3 > 0) {
                throw new RuntimeException(MessageConstant.ADD_MENU_PATH_FAIL);
            }

            menuDao.addMenu(menu);
        }
    }

    @Override
    public List<Map> findParentNameAndId() {
        List<Map> parentNameAndId = menuDao.findParentNameAndId();
        Map map = new HashMap();
        map.put("设置成一级菜单", null);
        parentNameAndId.add(map);
        return parentNameAndId;
    }
}
